﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Web;
using System.Web.Mvc;
using System.Linq;
using System.Web.Security;
using DataModel.Managers;
using DataModel.Managers.SubManage;
using DataModel.Models;

namespace UniversityPortal.Controllers
{
    public class ScheduleController : Controller
    {
        //[UAuthorize(UserRoles = "Student")]
        public ActionResult Index()
        {
            var dm = new DepartmentManager();

            var depList = dm.GetAllDepartments().Select(dep => new SelectListItem() { Text = dep.ShortName, Value = dep.DepartmentID.ToString() });
            return View("GroupList", depList);
        }

        public ActionResult GetGroupSchedule(int id, string fromDateString, string toDateString)
        {
            var manager = new ScheduleManager();
            DateTime fromDate;
            DateTime toDate;
            // TODO : fix solution
            if (!DateTime.TryParse(fromDateString, out fromDate))
            {
                fromDate = DateTime.Today;
            }
            if (!DateTime.TryParse(toDateString, out toDate))
            {
                toDate = fromDate.AddDays(7);
            }



            if (fromDate > toDate)
            {
                var date = fromDate;
                fromDate = toDate;
                toDate = date;
            }
            var schedule = manager.GetScheduleByGroup(id, fromDate, toDate);
            return View("GetGroupSchedule", schedule);
        }

        //[Custom(Role = "Admin")]
        public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return RedirectToAction("Index");
            }
            var sm = new ScheduleManager();
            var sch = sm.GetSemesterShchedule((long)id, 7);

            //cleanup users editing data
            Session["EditingLessons"] = null;

            return View(sch);
        }



        public ActionResult EditLessonInline(string id)
        {
            var guid = new Guid(id);
            var lessonManager = new LessonManager();
            var lesson = lessonManager.GetLesson(guid);
            var helper = new PeriodicityHelper();
            var request = new LessonRequest
                              {
                                  Lessonid = lesson.LessonID,
                                  Auditoryid = lesson.Auditory.ID,
                                  Begindate = lesson.BeginDate,
                                  Enddate = lesson.EndDate,
                                  BeginTime = lesson.BeginTime,
                                  EndTime = lesson.EndTime,
                                  Lessonypeid = lesson.LessonType.ID,
                                  Professorid = lesson.Professor.ID,
                                  periodicity = lesson.Periodicity,
                                  Periodicitymask = helper.GetBoolMask(lesson.Periodicity, lesson.PeriodicityMask),
                                  Subjectid = lesson.Subject.ID,
                                  Weekday = lesson.WeekDay,
                                  Semester = lesson.Semester,
                                  GroupId = (new LessonManager()).GetGroupsOnLesson(guid)
                              };



            if (TryBeginEditLesson(guid))
            {
                return View(request);
            }
            else
            {
                return View("EditScheduleErrorMessage");
            }

        }

        public ActionResult AddLessonInline()
        {
            var guid = Guid.NewGuid();
            var lessonRequest = new LessonRequest
                {
                    Lessonid = guid,
                };
            return View(lessonRequest);
        }

        private bool TryBeginEditLesson(Guid lessonID)
        {
            var editingLessonItem = new EditingLessonItem { ChangeTime = DateTime.UtcNow, LessonID = lessonID };

            var usersEditingLessons = Session["EditingLessons"] as List<EditingLessonItem>;
            if (usersEditingLessons != null)
            {
                if (usersEditingLessons.FindIndex(item => item.LessonID == lessonID) >= 0)
                {
                    return false;
                }
            }
            else
            {
                usersEditingLessons = new List<EditingLessonItem>();
            }

            usersEditingLessons.Add(editingLessonItem);
            Session["EditingLessons"] = usersEditingLessons;

            var commonEditingLessonItem = new EditingLessonItem { ChangeTime = new DateTime(0), LessonID = lessonID, EditorsCount = 1 };
            HttpContext.Application.Lock();
            List<EditingLessonItem> commonEditingLessons =
                HttpContext.Application["EditingLessons"] as List<EditingLessonItem> ?? new List<EditingLessonItem>();

            int index;
            if ((index = commonEditingLessons.FindIndex(l => l.LessonID == lessonID)) < 0)
            {
                commonEditingLessons.Add(commonEditingLessonItem);
            }
            else
            {
                commonEditingLessons[index].EditorsCount++;
            }
            HttpContext.Application["EditingLessons"] = commonEditingLessons;
            HttpContext.Application.UnLock();
            return true;
        }

        public ActionResult GetSpecialities()
        {
            DepartmentManager dm = new DepartmentManager();
            List<SelectListItem> specialities = new List<SelectListItem>();
            Guid id = Guid.Parse(Request.QueryString[0]);
            foreach (var spec in dm.GetDepartmentSpecialities(id))
            {
                specialities.Add(new SelectListItem()
                {
                    Text = spec.ShortName,
                    Value = spec.SpecialityID.ToString()
                });
            }
            return PartialView("GetSpecialities", specialities);
        }

        public ActionResult GetGroups()
        {
            List<SelectListItem> groupList = new List<SelectListItem>();
            Guid id = Guid.Parse(Request.QueryString[0]);
            var gm = new GroupManager();
            foreach (var gr in gm.GetGroupsInSpeciality(id))
            {
                groupList.Add(new SelectListItem()
                {
                    Text = gr.Number.ToString(),
                    Value = gr.Id.ToString()
                });
            }
            return PartialView("GetGroups", groupList);
        }

        [HttpPost]
        public ActionResult EditLessonInline(LessonRequest lesson)
        {
            if (ModelState.IsValid)
            {
                if (TrySaveLesson(lesson) == false)
                {
                    return View("EditScheduleErrorMessage");
                }
            }
            return RedirectToAction("Edit");
        }

        [HttpPost]
        public ActionResult AddLessonInline(LessonRequest lesson)
        {
            if (ModelState.IsValid)
            {
                SaveLesson(lesson);
            }

            return RedirectToAction("Edit");
        }

        private bool TrySaveLesson(LessonRequest lesson)
        {
            bool isSuccessfull;
            var usersEditingLessons = Session["EditingLessons"] as List<EditingLessonItem>;
            //Debug.Assert(usersEditingLessons == null, "usersEditingLessons cannot be null");
            HttpContext.Application.Lock();
            var editingLessons = HttpContext.Application["EditingLessons"] as List<EditingLessonItem>;
            HttpContext.Application.UnLock();

            if (usersEditingLessons != null && editingLessons != null)
            {
                int userEditingLessonIndex = usersEditingLessons.FindIndex(item => item.LessonID == lesson.Lessonid);
                int editingLessonIndex = editingLessons.FindIndex(item => item.LessonID == lesson.Lessonid);
                if ((userEditingLessonIndex < 0) || (editingLessonIndex < 0))
                {
                    throw new Exception("Illegal command. No necessary data in Session or Application storage.");
                }

                if (editingLessons[editingLessonIndex].ChangeTime >
                    usersEditingLessons[userEditingLessonIndex].ChangeTime)
                {
                    isSuccessfull = false;
                }
                else
                {
                    // save without problems
                    var lesManager = new LessonManager();
                    lesManager.UpdateLesson(lesson);
                    usersEditingLessons.RemoveAt(userEditingLessonIndex);
                    Session["EditingLessons"] = usersEditingLessons;

                    editingLessons[editingLessonIndex].EditorsCount--;
                    editingLessons[editingLessonIndex].ChangeTime = DateTime.UtcNow;
                    if (editingLessons[editingLessonIndex].EditorsCount <= 0)
                    {
                        editingLessons.RemoveAt(editingLessonIndex);
                    }
                    HttpContext.Application.Lock();
                    HttpContext.Application["EditingLessons"] = editingLessons;
                    HttpContext.Application.UnLock();

                    //var mailSender = new MailSender();
                    //mailSender.SendEditLessonData(lesson);
                    isSuccessfull = true;
                }
            }
            else
            {
                throw new Exception("Illegal command. No necessary data in Session or Application storage.");
            }
            return isSuccessfull;
        }

        /// <summary>
        /// Save new lesson data and correct Session or Application storage content
        /// </summary>
        /// <param name="lesson"></param>
        /// Exceptions: No necessary data in Session or Application storage. Illegal command
        public void SaveLesson(LessonRequest lesson)
        {
            var usersEditingLessons = Session["EditingLessons"] as List<EditingLessonItem> ?? new List<EditingLessonItem>();
            HttpContext.Application.Lock();
            var editingLessons = HttpContext.Application["EditingLessons"] as List<EditingLessonItem> ?? new List<EditingLessonItem>();
            HttpContext.Application.UnLock();

            int userEditingLessonIndex = usersEditingLessons.FindIndex(item => item.LessonID == lesson.Lessonid);
            int editingLessonIndex = editingLessons.FindIndex(item => item.LessonID == lesson.Lessonid);
            if (userEditingLessonIndex >= 0 || editingLessonIndex >= 0)
            {
                usersEditingLessons.RemoveAt(userEditingLessonIndex);
                Session["EditingLessons"] = usersEditingLessons;

                editingLessons[editingLessonIndex].EditorsCount--;
                if (editingLessons[editingLessonIndex].EditorsCount <= 0)
                {
                    editingLessons.RemoveAt(editingLessonIndex);
                }
                HttpContext.Application.Lock();
                HttpContext.Application["EditingLessons"] = editingLessons;
                HttpContext.Application.UnLock();      
            }
            var lesManager = new LessonManager();
            lesManager.UpdateLesson(lesson);
            //var mailSender = new MailSender();
            //mailSender.SendEditLessonData(lesson);
        }


        public ActionResult EditLessonAbort(string Id)
        {
            var lessonId = new Guid(Id);
            var usersEditingLessons = Session["EditingLessons"] as List<EditingLessonItem>;
            int index;
            if (usersEditingLessons != null)
            {
                index = usersEditingLessons.FindIndex(item => item.LessonID == lessonId);
                if (index >= 0)
                {
                    usersEditingLessons.RemoveAt(index);
                }
            }
            Session["EditingLessons"] = usersEditingLessons;

            HttpContext.Application.Lock();
            var editingLessons =
                HttpContext.Application["EditingLessons"] as List<EditingLessonItem>;
            if (editingLessons != null)
            {
                if ((index = editingLessons.FindIndex(item => item.LessonID == lessonId)) >= 0)
                {
                    editingLessons[index].EditorsCount--;
                    if (editingLessons[index].EditorsCount <= 0)
                        editingLessons.RemoveAt(index);
                }
                HttpContext.Application["EditingLessons"] = editingLessons;
            }
            HttpContext.Application.UnLock();

            return RedirectToAction("Edit");
        }

        [HttpGet]
        public ActionResult Import()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Import(HttpPostedFileBase file)
        {
            if (file != null && file.ContentLength > 0)
            {
                var path = Server.MapPath("/upload/" + Path.GetRandomFileName());
                var fileExtension = Path.GetExtension(file.FileName);
                file.SaveAs(path + fileExtension);
                var im = new ImportManager();
                im.LoadLessons(path + fileExtension);
            }
            return View();
        }

    }
}